/**
 * Electron预加载脚本 - TypeScript版本
 * 本文件在渲染进程加载前执行，用于在渲染进程和主进程之间建立安全的通信桥梁
 * 通过contextBridge.exposeInMainWorld方法将经过安全验证的API暴露给渲染进程
 */

// 导入所需模块
import { contextBridge, ipcRenderer } from 'electron'

console.log('预加载脚本已加载')

/**
 * 定义预加载API的接口
 */
interface ElectronAPI {
  /**
   * 发送消息到主进程
   * @param channel - 消息通道名称
   * @param data - 要发送的数据
   */
  sendMessage: (channel: string, data?: any) => void

  /**
   * 监听并接收来自主进程的消息
   * @param channel - 消息通道名称
   * @param func - 接收到消息时的回调函数
   */
  receiveMessage: (channel: string, func: (...args: any[]) => void) => void

  /**
   * 通知主进程用户已登录成功
   * 主进程收到此消息后会关闭登录窗口并打开主窗口
   */
  loginSuccess: () => void

  /**
   * 退出登录
   * 通知主进程用户已退出登录
   * 主进程收到此消息后会关闭主窗口并打开登录窗口
   */
  exitLogin: () => void

  /**
   * 添加好友
   * 通知主进程用户已添加好友
   * 主进程收到此消息后会关闭添加好友窗口并刷新好友列表
   */
  openAddUserWindow: () => void

  /**
   * 打开好友申请窗口
   */
  openFriendRequestWindow: () => void

  /**
   * 检查API是否可用
   * @returns 始终返回true，表示API可用
   */
  isAvailable: () => boolean

  /**
   * 发送WebSocket消息
   * @param data - 要发送的消息数据
   * @returns 发送结果
   */
  wsSend: (data: any) => Promise<any>

  /**
   * 检查WebSocket连接状态
   * @returns 连接状态
   */
  wsGetStatus: () => Promise<string>
  /**
   * 初始化WebSocket连接
   * @param userId - 用户ID
   * @param url - WebSocket服务器URL
   */
  wsInit: (userId: string, url: string) => Promise<any>

  /**
   * 断开WebSocket连接
   */
  wsDisconnect: () => Promise<any>

  /**
   * 监听WebSocket状态变化
   * @param callback - 处理状态变化的回调函数
   */
  onWsStatusChange: (callback: (status: string) => void) => void

  /**
   * 监听WebSocket消息
   * @param callback - 处理消息的回调函数
   */
  onWsMessage: (callback: (data: any) => void) => void

  /**
   * 移除WebSocket消息监听器
   * @param callback - 要移除的回调函数
   */
  offWsMessage: (callback: (data: any) => void) => void

  /**
   * 刷新好友申请列表
   * @returns
   */
  friendRequestUpdated: () => void

  onFriendRequestUpdate: (callback: (data: any) => void) => void

  /**
   * 操作应用程序配置存储
   */
  store: {
    set: (key: string, value: any) => Promise<void>
    get: (key: string) => Promise<any>
    delete: (key: string) => Promise<void>
  }

  /**
   * 数据库操作接口
   * 通过IPC与主进程通信，安全地执行数据库操作
   */
  database: {
    /**
     * 初始化数据库表结构
     */
    initTables: () => Promise<void>

    /**
     * 添加新消息
     * @param message 消息对象
     * @returns 操作结果，包含插入的ID
     */
    addMessage: (message: any) => Promise<any>

    /**
     * 更新消息状态
     * @param local_id 本地消息ID
     * @param status 新的消息状态
     * @returns 操作结果，包含影响的行数
     */
    updateMessageStatus: (local_id: string, status: number) => Promise<any>

    /**
     * 获取指定会话的消息列表
     * @param conversationId 会话ID
     * @param limit 限制返回的消息数量
     * @returns 消息数组
     */
    getMessagesByConversation: (
      conversationId: string,
      limit?: number
    ) => Promise<any[]>

    /**
     * 添加好友申请
     * @param friendRequest 好友申请对象
     * @returns 操作结果，包含插入的ID
     */
    addFriendRequest: (friendRequest: any) => Promise<any>

    /**
     * 获取好友申请列表
     * @param toUserId 接收好友申请的用户ID
     * @returns 好友申请数组
     */
    getFriendRequestsByToUserId: (
      toUserId: string,
      status?: string
    ) => Promise<any[]>

    /**
     * 更新好友申请状态
     * @param id 好友申请ID
     * @param status 新的状态
     * @returns 操作结果，包含影响的行数
     */
    updateFriendRequestStatus: (id: number, status: string) => Promise<any>

    /**
     * 关闭数据库连接
     */
    close: () => Promise<void>
  }
}

/**
 * 渲染进程可调用的Electron API集合
 * 提供经过安全验证的IPC通信方法
 */
const electronAPI: ElectronAPI = {
  /**
   * 发送消息到主进程
   * @param channel - 消息通道名称
   * @param data - 要发送的数据
   */
  sendMessage: (channel, data) => {
    const validChannels = ['ping', 'login-success']
    if (validChannels.includes(channel)) {
      console.log('preload -> 发送 IPC 消息:', channel, data)
      ipcRenderer.send(channel, data)
    }
  },

  /**
   * 监听并接收来自主进程的消息
   * @param channel - 消息通道名称
   * @param func - 接收到消息时的回调函数
   */
  receiveMessage: (channel, func) => {
    const validChannels = ['pong']
    if (validChannels.includes(channel)) {
      // 监听事件
      ipcRenderer.on(channel, (_event, ...args) => func(...args))
    }
  },

  /**
   * 通知主进程用户已登录成功
   */
  loginSuccess: () => {
    console.log('登录成功，通知主进程')
    ipcRenderer.send('login-success')
  },

  /**
   * 退出登录
   */
  exitLogin: () => {
    console.log('退出登录，通知主进程')
    ipcRenderer.send('exit-login')
  },

  /**
   * 打开添加好友窗口
   */
  openAddUserWindow: () => {
    console.log('打开添加好友窗口，通知主进程')
    ipcRenderer.send('open-add-user-window')
  },

  /**
   * 打开好友申请窗口
   */
  openFriendRequestWindow: () => {
    console.log('打开好友申请窗口，通知主进程')
    ipcRenderer.send('open-friend-request-window')
  },

  /**
   * 刷新好友申请列表
   */
  friendRequestUpdated: () => {
    console.log('刷新好友申请列表，通知主进程')
    ipcRenderer.invoke('friend-request-updated')
  },

  /**
   * 监听好友申请列表更新
   */
  onFriendRequestUpdate: (callback) => {
    console.log('注册好友申请列表更新监听')
    ipcRenderer.on('friend-request-refresh', (_event, data) => {
      console.log('收到好友申请列表更新:', data)
      callback(data)
    })
  },

  /**
   * 检查API是否可用
   * @returns 始终返回true
   */
  isAvailable: () => true,

  /**
   * 通过主进程代理发送WebSocket消息
   */
  wsSend: (data) => {
    console.log('preload -> 通过IPC发送WebSocket消息:', data)
    return ipcRenderer.invoke('ws-send', data)
  },

  /**
   * 检查WebSocket连接状态
   */
  wsGetStatus: () => {
    console.log('通过IPC获取WebSocket状态')
    return ipcRenderer.invoke('ws-get-status')
  },

  /**
   * 初始化WebSocket连接
   */
  wsInit: (userId, url) => {
    console.log('通过IPC初始化WebSocket:', { userId, url })
    return ipcRenderer.invoke('ws-init', { userId, url })
  },

  /**
   * 断开WebSocket连接
   */
  wsDisconnect: () => {
    console.log('通过IPC断开WebSocket连接')
    return ipcRenderer.invoke('ws-disconnect')
  },

  /**
   * 监听WebSocket状态变化
   */
  onWsStatusChange: (callback) => {
    console.log('注册全局WebSocket状态监听')
    ipcRenderer.on('ws-status-change', (_event, status) => {
      console.log('收到WebSocket状态变化:', status)
      callback(status)
    })
  },

  /**
   * 监听WebSocket消息
   */
  onWsMessage: (callback) => {
    console.log('注册全局WebSocket消息监听')
    ipcRenderer.on('ws-message', (_event, data) => {
      console.log('收到WebSocket消息:', data)
      callback(data)
    })
  },

  /**
   * 移除WebSocket消息监听
   */
  offWsMessage: (callback) => {
    console.log('移除全局WebSocket消息监听')
    ipcRenderer.off('ws-message', callback)
  },

  /**
   * 操作应用程序配置存储
   */
  store: {
    set: (key, value) => ipcRenderer.invoke('store-set', key, value),
    get: (key) => ipcRenderer.invoke('store-get', key),
    delete: (key) => ipcRenderer.invoke('store-delete', key)
  },

  /**
   * 数据库操作接口
   * 通过IPC与主进程通信，安全地执行数据库操作
   */
  database: {
    // 初始化数据表
    initTables: () => ipcRenderer.invoke('database-init-tables'),
    // 消息相关
    addMessage: (message) =>
      ipcRenderer.invoke('database-add-message', message),
    updateMessageStatus: (local_id, status) =>
      ipcRenderer.invoke('database-update-message-status', local_id, status),
    getMessagesByConversation: (conversationId, limit = 30) =>
      ipcRenderer.invoke('database-get-messages', conversationId, limit),
    // 好友申请相关
    addFriendRequest: (friendRequest: any) =>
      ipcRenderer.invoke('database-add-friend-request', friendRequest),
    getFriendRequestsByToUserId: (toUserId: string, status?: string) =>
      ipcRenderer.invoke(
        'database-get-friend-requests-by-to-user-id',
        toUserId,
        status
      ),
    // 更新好友申请状态
    updateFriendRequestStatus: (id: number, status: string) =>
      ipcRenderer.invoke('database-update-friend-request-status', id, status),
    // 关闭数据库
    close: () => ipcRenderer.invoke('database-close')
  }
}

/**
 * 扩展Window接口，添加electronAPI、__electron_preload_loaded属性和validateElectronAPI方法
 */
declare global {
  interface Window {
    electronAPI: ElectronAPI
    __electron_preload_loaded: boolean
    validateElectronAPI?: () => boolean
  }
}

/**
 * 将定义的API暴露到渲染进程的全局作用域
 * 使用try-catch块确保即使注入失败也不会中断应用运行
 */
// 标记注入状态
let injectionSuccessful = false

// 根据 contextIsolation 状态选择注入方式
if (process.contextIsolated) {
  // 上下文隔离启用时使用 contextBridge
  try {
    // 暴露electronAPI
    contextBridge.exposeInMainWorld('electronAPI', electronAPI)
    // 暴露一个标志，用于前端检测Electron环境
    contextBridge.exposeInMainWorld('__electron_preload_loaded', true)
    injectionSuccessful = true
    console.log('✅ electronAPI 通过 contextBridge 注入成功')
    console.log('✅ __electron_preload_loaded 标志已设置')

    // 立即验证注入是否成功
    // 注意：由于contextBridge的工作机制，这里不能直接访问window.electronAPI
    // 但我们可以确认注入过程没有抛出异常
    console.log('✅ 注入过程完成，注入状态标记为成功')
  } catch (error) {
    console.error('❌ electronAPI 注入失败:', error)
    injectionSuccessful = false
  }
} else {
  // 上下文隔离禁用时直接挂载
  try {
    window.electronAPI = electronAPI
    window.__electron_preload_loaded = true
    injectionSuccessful = true
    console.log('✅ electronAPI 直接挂载成功')
    console.log('✅ __electron_preload_loaded 标志已设置')

    // 立即验证挂载是否成功
    console.log('✅ 立即验证 electronAPI 可用:', !!window.electronAPI)
  } catch (error) {
    console.error('❌ electronAPI 挂载失败:', error)
    injectionSuccessful = false
  }
}

/**
 * 监听DOM内容加载完成事件
 * 确保在DOM完全加载后再执行后续操作
 */
window.addEventListener('DOMContentLoaded', () => {
  console.log('🌐 DOM 加载完成')

  // 检查electronAPI是否可用
  // 注意：当启用contextIsolation时，我们不能直接在预加载脚本中访问window.electronAPI
  // 所以我们使用注入状态标志来表示是否成功注入
  const electronApiAvailable = process.contextIsolated
    ? injectionSuccessful
    : !!window.electronAPI
  console.log('🔍 electronAPI 可用:', electronApiAvailable)
  console.log('🔍 注入状态标志:', injectionSuccessful)
  console.log('🔍 上下文隔离状态:', process.contextIsolated)

  // 发送事件通知 Vue 组件 API 已就绪
  window.dispatchEvent(new Event('electron-api-ready'))
})

// 添加一个函数，用于在渲染进程中验证API是否正确暴露
if (!process.contextIsolated) {
  window.validateElectronAPI = () => {
    console.log('📋 electronAPI 验证结果:', {
      exists: !!window.electronAPI,
      methods: window.electronAPI ? Object.keys(window.electronAPI) : [],
      isAvailableWorks: window.electronAPI?.isAvailable
        ? window.electronAPI.isAvailable()
        : false
    })
    return !!window.electronAPI
  }
}
